package com.ctosb.classviewer.clazz.util;

import com.ctosb.classviewer.ClassReader;
import com.ctosb.classviewer.clazz.ClassFile;
import com.ctosb.classviewer.clazz.attr.*;
import com.ctosb.classviewer.clazz.cp.CONSTANT_Utf8_info;

import java.util.HashMap;
import java.util.Map;

public class Attribute_infoParse {

    private static Map<String, Class<? extends Attribute_info>> map = new HashMap<>();

    static {
        setAttribute(ConstantValue_attribute.class);
        setAttribute(Code_attribute.class);
        setAttribute(StackMapTable_attribute.class);
        setAttribute(Exceptions_attribute.class);
        setAttribute(InnerClasses_attribute.class);
        setAttribute(EnclosingMethod_attribute.class);
        setAttribute(Synthetic_attribute.class);
        setAttribute(Signature_attribute.class);
        setAttribute(SourceFile_attribute.class);
        setAttribute(SourceDebugExtension_attribute.class);
        setAttribute(LineNumberTable_attribute.class);
        setAttribute(LocalVariableTable_attribute.class);
        setAttribute(LocalVariableTypeTable_attribute.class);
        setAttribute(Deprecated_attribute.class);
        setAttribute(RuntimeVisibleAnnotations_attribute.class);
        setAttribute(RuntimeInvisibleAnnotations_attribute.class);
        setAttribute(RuntimeVisibleParameterAnnotations_attribute.class);
        setAttribute(RuntimeInvisibleParameterAnnotations_attribute.class);
        setAttribute(AnnotationDefault_attribute.class);
        setAttribute(BootstrapMethods_attribute.class);
    }

    private static void setAttribute(Class clazz) {
        String name = clazz.getSimpleName().replace("_attribute", "");
        map.put(name, clazz);
    }

    public static Attribute_info[] parse(short length, ClassReader classReader, ClassFile classFile) {
        Attribute_info[] attribute_infos = new Attribute_info[length & 0xffff];
        for (int i = 0; i < attribute_infos.length; i++) {
            short attribute_name_index = classReader.readShort();
            CONSTANT_Utf8_info cp_info = (CONSTANT_Utf8_info) classFile.getConstant_pool()[attribute_name_index & 0xffff];
            String attrType = new String(cp_info.getBytes());
            Class<? extends Attribute_info> clazz = map.get(attrType);
            try {
                attribute_infos[i] = clazz.newInstance()
                        .setAttribute_name_index(attribute_name_index)
                        .parse(classReader, classFile);
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
        return attribute_infos;
    }


}
